home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / i / internet / software / tnftpsr / tnftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-25  |  27.4 KB  |  1,162 lines

  1. /************************************
  2.     ftp client for TUW-TCP or ANS
  3. ************************************/
  4. /* P. Mayer fortec TU Vienna 1992,1993  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <aes.h>
  11. #include <tos.h>
  12. #include <ext.h>
  13. #include "cookie.h"
  14. #include "inetcust.h" 
  15. #include "tcpdef.h"
  16. #include "tndefs.h"    
  17.  
  18. #define log(x) w_output(p_ftp_win,x,strlen(x))
  19.  
  20. #define FTP_CMD        21
  21. #define FTP_DATA    20
  22.  
  23. #define BUFFERSIZE (0x7fa4L)
  24. #define DATASIZE   BUFFERSIZE+2
  25. #define FTPWND     5824L
  26. #define DIRWND     1024L
  27. #define FTPDISPLAYSIZE    128
  28.  
  29. static char *inputprompt = "\r\nTUW-FTP> ";
  30. static char *str;
  31.  
  32. static int  replpos;
  33. static char logstr[100];
  34. static char ftp_respbuf[120];
  35.  
  36. static char *ftp_script[3];
  37. static char ftpscriptbuf[3][100];
  38. static int  ftp_scriptline;
  39. static char ftp_retrfile[80];
  40. static char tempfile[MAXPATH];
  41. static char ftp_echoMode;
  42. static char *px;
  43.  
  44. static long btime, tcount;
  45. static char transfermode = 'a';
  46. static int  puthandle,gethandle,dataindex;
  47. static int  lendata,getlen;
  48. static char sendpass,senduser,isport,interactive,verbose,mget,mput,getline,verb_cancel;
  49.  
  50. static struct wi_str *p_ftp_win;
  51.  
  52. static char ftp_outbuf[80];
  53. static char ftp_inbuf[80];
  54. static char ftp_outbufix, ftp_outbuflen, ftp_inbuflen;
  55. static int  ftp_rcvState;
  56. static char ftp_databuffer[DATASIZE];
  57. static unsigned char abor_cmd1[2] = 
  58. {TN_IAC,TN_IP};
  59. static unsigned char abor_cmd2[7] = 
  60. {TN_DM,'A','B','O','R','\r','\n'};
  61.  
  62.  
  63. int ftpbusy = 0;
  64.  
  65. extern char keeppath[MAXPATH];
  66. extern void w_output(struct wi_str *wp, unsigned char *ptr, short charcount);
  67. extern void w_info(struct wi_str *wp, char *name);
  68. extern void traps(void);
  69. extern int connect(int port, char * host, int tcp_id);
  70. extern int ftp_data, ftp_ctl;
  71. extern DESTI desti, my;
  72. extern TCPSTAT tstat;
  73.  
  74. void  dodir(int list,char *dirpath);
  75. int process_cmd(void);
  76. int setport(void);
  77. int do_mget(void);
  78. int do_mput(void);
  79. void dosify(char *);
  80.  
  81. #define DOABORT \
  82.           tcp_write(ftp_ctl,abor_cmd1,2,PUSH,NO_URGENT);\
  83.           tcp_write(ftp_ctl,abor_cmd1,1,PUSH,URGENT);\
  84.           tcp_write(ftp_ctl,abor_cmd2,7,PUSH,NO_URGENT);\
  85.  
  86. #define ftp_StateGETCMD      0       /* get a command from the user */
  87. #define ftp_StateDOCMD       1       /* prepare command */
  88. #define ftp_StateSENDCOMMAND 2       /* command beeing sent */
  89. #define ftp_StateRCVRESP     3       /* awaiting first response */
  90. #define ftp_StateINRESP      4       /* awaiting more response */
  91. #define ftp_StateCLOSING     5       /* closing data connection */
  92. #define ftp_StateWAITCOMPL   6       /* wait for closing data connection */
  93.  
  94. #define PUTOK                 0
  95. #define PUTCLOSED           1
  96. #define PUTABORT              2
  97.  
  98. #define GETOK                 0
  99. #define GETCLOSED             1
  100. #define GETABORT              2
  101.  
  102. #define CTLOK                 0
  103. #define CTLABORT              2
  104.  
  105. int getHandler(void)
  106. {
  107.   int i;
  108.   long t;
  109.  
  110. do
  111. {
  112.   if((int)tcp_stat(ftp_data,&tstat) < ESTABLISHED)
  113.   {
  114.    return 0;
  115.   }
  116.   if(gethandle > 0)
  117.     i = (int)tcp_read(ftp_data,&ftp_databuffer[getlen],(int)(BUFFERSIZE - getlen));
  118.   else
  119.     i = (int)tcp_read(ftp_data,&ftp_databuffer,FTPDISPLAYSIZE);
  120.  
  121.   if(i < 0)
  122.   {
  123.     tcp_close(ftp_data);
  124.     ftp_data = -1;
  125.     if(gethandle > 0)
  126.     {
  127.       if(getlen)
  128.       {
  129.         if(getlen != Fwrite(gethandle,(long)getlen,ftp_databuffer))
  130.         {
  131.           log("\r\nWrite error!\r\n"); 
  132.           DOABORT
  133.           mget = mput = 0;
  134.           ftp_data = -1;
  135.           Fclose(gethandle);
  136.           gethandle = mget = 0;
  137.           ftp_inbuflen = 0;
  138.           ftp_rcvState = ftp_StateGETCMD;
  139.           return GETABORT;
  140.         }
  141.       }
  142.       if(gethandle != mget) Fclose(gethandle);
  143.       else if (mget) Fseek(0L,mget,0);
  144.     }
  145.     gethandle=getlen=0;
  146.     t=(clock()-btime)/CLK_TCK;
  147.     if(t == 0) t = 1;
  148.     sprintf(logstr,"\r\n%ld bytes transferred in %ld seconds (%ld bytes/sec).\r\n",tcount,t,tcount/t);
  149.     log(logstr);
  150.     return GETCLOSED;
  151.   }
  152.   else/* if(i)*/
  153.   {
  154. /*  traps();*/
  155.     ftp_databuffer[getlen+i] = 0;
  156.     if (gethandle > 0)
  157.     {
  158.       getlen += i;
  159.       if(getlen == BUFFERSIZE)
  160.       {
  161.         if(getlen != Fwrite(gethandle,(long)getlen,ftp_databuffer))
  162.         {
  163.           log("\r\nWrite error!\r\n");
  164.           DOABORT
  165.           mget = mput = 0;
  166.           ftp_data = -1;
  167.           Fclose(gethandle);
  168.           gethandle = mget = 0;
  169.           ftp_inbuflen = 0;
  170.           ftp_rcvState = ftp_StateGETCMD;
  171.           return GETABORT;
  172.         }
  173.         
  174.         
  175.         getlen = 0;
  176.       }
  177.       /*else if(i == 0) while(clock() == clock());*/
  178.     }
  179.     else
  180.     {
  181.       if(transfermode == 'i')
  182.       {
  183.         p_ftp_win->lfmode = 1;
  184.         log(ftp_databuffer);
  185.         p_ftp_win->lfmode = 0;
  186.       }
  187.       else log(ftp_databuffer);
  188.     }
  189.     tcount += i;
  190.   }
  191. }while(i && gethandle > 0);
  192.   return GETOK;
  193. }
  194.  
  195. int putHandler(void)
  196. {
  197.   int i;
  198.   long t;
  199.  
  200.   if((int)tcp_stat(ftp_data,&tstat) < ESTABLISHED) return 0;
  201.  
  202.   i=0;
  203.   
  204. do
  205. {
  206.   if(lendata==0)
  207.   {
  208.     lendata = (int)Fread(puthandle,BUFFERSIZE,ftp_databuffer);
  209.     if(lendata > 0) tcount += lendata;
  210.     dataindex=0;
  211.     if(lendata <= 0)
  212.     {
  213.       Fclose(puthandle);
  214.       tcp_close(ftp_data);
  215.       ftp_data = -1;
  216.       puthandle = 0;
  217.       t=(clock()-btime)/CLK_TCK;
  218.       if(t == 0) t = 1;
  219.       if(lendata == 0)
  220.       {
  221.         sprintf(logstr,"\r\n%ld bytes transferred in %ld seconds (%ld bytes/sec).\r\n",tcount,t,tcount/t);
  222.         log(logstr);
  223.         return PUTCLOSED;
  224.       }
  225.       else
  226.       {
  227.         log("Read error!\r\n");
  228.         return PUTABORT;
  229.       }
  230.     }
  231.   }
  232.  
  233.   {
  234.     if(tcp_stat(ftp_data,&tstat) == ESTABLISHED)
  235.     {
  236.       i = (int)tcp_write(ftp_data,&ftp_databuffer[dataindex],lendata-dataindex,PUSH,NO_URGENT);
  237.       traps();
  238.       if(i < 0)
  239.       {
  240.         if(puthandle > 0) Fclose(puthandle);
  241.         log("Data connection closed.\r\n"); 
  242.         puthandle = 0;
  243.         tcp_close(ftp_data);
  244.         ftp_data = -1;
  245.         return PUTABORT;
  246.       }
  247.       else
  248.       {
  249.         dataindex += i;
  250.         if(dataindex >= lendata)  lendata = 0;
  251.       }
  252.     }
  253.   }
  254. }while(i > 0);
  255.   return PUTOK;
  256. }
  257.  
  258. int ftp_check()
  259. {
  260.   char *s;
  261.   int i;
  262.  
  263.   if(gethandle) getHandler();
  264.   if(puthandle) putHandler();  
  265.  
  266.   if(ftp_rcvState == ftp_StateWAITCOMPL && (isport || (!gethandle && !puthandle)))
  267.   {
  268.     if(!isport && !mget && !mput) log(inputprompt);
  269.     ftp_rcvState = ftp_StateGETCMD;
  270.     isport = 0;
  271.   }
  272.  
  273.   i = (int)tcp_read(ftp_ctl,&ftp_respbuf[replpos],(int)sizeof(ftp_respbuf)-1-replpos);
  274.   if(i < 0)
  275.   {
  276.     w_info(p_ftp_win,"<Status: connection closed.>");
  277.     if(ftp_data > 0) tcp_close(ftp_data);
  278.     ftp_data = -1;
  279.     replpos = 0;
  280.     if(gethandle > 0) Fclose(gethandle);
  281.     if(puthandle > 0) Fclose(puthandle);
  282.     gethandle = puthandle = 0;
  283.     return CTLABORT;
  284.   }
  285.   else if(i)
  286.   {
  287.     ftp_respbuf[replpos+i] = 0;
  288.     replpos += i;
  289.  
  290.     if(ftp_rcvState == ftp_StateRCVRESP)
  291.     {
  292.       ftp_rcvState = ftp_StateINRESP;
  293.     }  
  294.  
  295.     switch(ftp_rcvState) 
  296.     {
  297.     case ftp_StateRCVRESP:
  298.     case ftp_StateINRESP:
  299.     case ftp_StateWAITCOMPL:
  300.       {
  301.         do
  302.         {
  303.           s = strchr(ftp_respbuf,'\n');
  304.           if(s)
  305.           {
  306.             if (( ftp_respbuf[0] == '2' || ftp_respbuf[0] == '3' 
  307.                 || ftp_respbuf[0] == '4' || ftp_respbuf[0] == '5') 
  308.             && ftp_respbuf[3] == ' ')
  309.             {
  310.               if (( ftp_respbuf[0] == '4' || ftp_respbuf[0] == '5') 
  311.               && ftp_respbuf[3] == ' ')
  312.               {
  313.                 if(gethandle > 0) Fclose(gethandle);
  314.                 if(puthandle > 0) Fclose(puthandle);
  315.                 gethandle = puthandle = 0;
  316.               } 
  317.               ftp_rcvState = ftp_StateWAITCOMPL;
  318.             }
  319.             *s = 0;
  320.             if(((verbose || verb_cancel) && (isport || gethandle != -1)) || ftp_respbuf[0] == '4' || ftp_respbuf[0] == '5')
  321.             {
  322.               log(ftp_respbuf);
  323.               if(transfermode == 'i') log("\r");
  324.               log("\n");
  325.             }
  326.  
  327.             if ( ftp_respbuf[0] == '3' && ftp_respbuf[1] == '3' 
  328.                 && ftp_respbuf[2] == '1' && ftp_respbuf[3] == ' ')
  329.               sendpass = 1; 
  330.  
  331.             strcpy(ftp_respbuf, s+1);
  332.             replpos = (int)strlen(ftp_respbuf);
  333.           }  
  334.         }
  335.         while(s);  
  336.         break;
  337.       }
  338.     }
  339.   }
  340.   return CTLOK;
  341. }
  342.  
  343. int ftp_application(struct wi_str *wp)
  344. {
  345.   int i;
  346.   char *s;
  347.   int ftp_check(void);
  348.   int putHandler(void);
  349.   int getHandler(void);
  350.  
  351.   p_ftp_win = wp;
  352.  
  353.   switch (ftp_rcvState) 
  354.   {
  355.   case ftp_StateGETCMD:
  356.     verb_cancel = 0;
  357.     if(ftp_check() == CTLABORT) return 2;
  358.  
  359.     if(ftp_scriptline >= 0) 
  360.     {
  361.  
  362.       s = ftp_script[ftp_scriptline];
  363.       if ( s == NULL )
  364.       {
  365.         if(mget)
  366.         {
  367.           if(do_mget())
  368.             ftp_rcvState = ftp_StateDOCMD;
  369.         }
  370.         else if(mput)
  371.         {
  372.           if(do_mput())
  373.             ftp_rcvState = ftp_StateDOCMD;
  374.         }
  375.         else
  376.         {
  377.           ftp_scriptline = -1;
  378.           ftp_inbuflen = 0;
  379.           break;
  380.         }
  381.       }
  382.       else
  383.       {
  384.         ftp_scriptline++;
  385.         strcpy(ftp_outbuf,s);
  386.         ftp_outbuflen = (int)strlen((char *)ftp_outbuf);
  387.         ftp_outbufix = 0;
  388.         ftp_rcvState = ftp_StateSENDCOMMAND;
  389.       }
  390.     }
  391.     else if(sendpass)
  392.     {
  393.       if(!getline)
  394.       {
  395.         getline = 1;
  396.         log("Password: ");
  397.         ftp_echoMode = 0;
  398.       }
  399.       else if(getline == 2)
  400.       {
  401.         strcpy(ftp_outbuf,"pass ");
  402.         strcat(ftp_outbuf,ftp_inbuf);
  403.         strcat(ftp_outbuf,"\r\n");
  404.         ftp_outbuflen = (int)strlen((char *)ftp_outbuf);
  405.         ftp_outbufix = 0;
  406.         ftp_rcvState = ftp_StateSENDCOMMAND;
  407.         ftp_echoMode = 1;
  408.         sendpass = getline = 0;
  409.       }
  410.     }
  411.     else if(senduser)
  412.     {
  413.       if(!getline)
  414.       {
  415.         getline = 1;
  416.         log("Username: ");
  417.         ftp_echoMode = 1;
  418.       }
  419.       else if(getline == 2)
  420.       {
  421.         strcpy(ftp_outbuf,"user ");
  422.         strcat(ftp_outbuf,ftp_inbuf);
  423.         strcat(ftp_outbuf,"\r\n");
  424.         ftp_outbuflen = (int)strlen((char *)ftp_outbuf);
  425.         ftp_outbufix = 0;
  426.         ftp_rcvState = ftp_StateSENDCOMMAND;
  427.         ftp_echoMode = 1;
  428.         senduser = getline = 0;
  429.       }
  430.     }
  431.     break;
  432.  
  433.   case ftp_StateRCVRESP:
  434.   case ftp_StateINRESP:
  435.   case ftp_StateWAITCOMPL:
  436.     if(ftp_check() == 2) return 2;
  437.     break;
  438.  
  439.   case ftp_StateDOCMD:
  440.     {
  441.       if(process_cmd())
  442.       {
  443.         ftp_rcvState = ftp_StateGETCMD;
  444.         break;
  445.       }
  446.     }
  447.   case ftp_StateSENDCOMMAND:
  448.     if(ftp_outbuflen - ftp_outbufix > 0)
  449.     {
  450.       i = (int)tcp_write(ftp_ctl,&ftp_outbuf[ftp_outbufix],ftp_outbuflen-ftp_outbufix,PUSH,NO_URGENT);
  451.       ftp_outbufix += i;
  452.     }
  453.     else
  454.     {
  455.       ftp_inbuflen = 0;
  456.       ftp_rcvState = ftp_StateRCVRESP;
  457.       replpos = 0;
  458.     }
  459.     break;
  460.   }
  461.  
  462.   return 0;
  463. }
  464.  
  465. int ftpinit(struct wi_str * wp, char *user, char *passwd)
  466. {
  467.   char * tempf;
  468.   
  469.   p_ftp_win = wp;
  470.   if(GetIPAddr(NULL,my.IPAddr))
  471.   {
  472.     log("Error: don't know my Internetaddress.\r\n");
  473.     return 2;
  474.   }
  475.  
  476.   sendpass = isport = getline = verb_cancel = 0;
  477.   ftp_data = -1;
  478.   puthandle = gethandle = mget = mput = 0;
  479.   /* set up the script for this session */
  480.   ftp_script[0] = NULL;
  481.   ftp_script[1] = NULL;
  482.   ftp_script[2] = NULL;
  483.   ftp_echoMode = interactive = verbose = 1;
  484.   ftp_scriptline = -1;
  485.   if(*user)
  486.   {
  487.     sprintf(ftpscriptbuf[0],"user %s\r\n",user);
  488.     ftp_scriptline = 0;
  489.     ftp_script[0] = ftpscriptbuf[0];
  490.     if(*passwd)
  491.     {
  492.       sprintf(ftpscriptbuf[1],"pass %s\r\n",passwd);
  493.       ftp_script[1] = ftpscriptbuf[1];
  494.     }
  495.   }
  496.   else senduser = 1;
  497.   /* set up state variables */
  498.   ftp_rcvState = ftp_StateRCVRESP;
  499.   replpos = ftp_inbuflen = 0;
  500.   tempf = getenv("FTPTMP");
  501.   if(tempf == NULL) strcpy(tempfile,"C:\\TMP\\ftp__tmp.tmp");
  502.   else strcpy(tempfile,tempf);
  503.   return 0;
  504. }
  505.  
  506. void handle_key(struct wi_str *wp, char key)
  507. {
  508.   w_info(p_ftp_win,"<Status: connected.>");
  509.   p_ftp_win = wp;
  510.   ftp_inbuf[ftp_inbuflen] = 0;
  511.  
  512.   switch (key) 
  513.   {
  514.   case 'H' & 037:
  515.   case 0177:
  516.     if ( ftp_inbuflen > 0 ) 
  517.     {
  518.       ftp_inbuflen--;
  519.       if(!stricmp(ftp_inbuf,"pass ")) ftp_echoMode = 1;
  520.       if(ftp_echoMode) log("\b \b");
  521.     }
  522.     break;
  523.  
  524.   case 'R' & 037:
  525.     if ( ftp_echoMode )
  526.     {
  527.       log(inputprompt);
  528.       log(ftp_inbuf);
  529.     }
  530.     break;
  531.  
  532.   case 033:
  533.     if(!sendpass) ftp_echoMode = ! ftp_echoMode;
  534.     break;
  535.   case 'C' & 037:
  536.     if(ftp_rcvState != ftp_StateGETCMD || mget || mput)
  537.     {
  538.       ftp_echoMode = 1;
  539.       sendpass = senduser = 0;
  540.       DOABORT
  541.       mget = mput = 0;
  542.       ftp_data = -1;
  543.       if(gethandle > 0) Fclose(gethandle);
  544.       if(puthandle) Fclose(puthandle);
  545.       gethandle = 0;
  546.       puthandle = 0;
  547.       ftp_inbuflen = 0;
  548.       log(inputprompt);
  549.       ftp_rcvState = ftp_StateGETCMD;
  550.     }
  551.     else
  552.     {
  553.       ftp_inbuflen = 0;
  554.       log(inputprompt);
  555.     }
  556.     break;
  557.   case '\r':
  558.     log("\r\n");
  559.     if(!getline)
  560.     {
  561.      if(ftp_rcvState == ftp_StateGETCMD)
  562.      {
  563.       ftp_echoMode = 1;
  564.       sendpass = senduser = 0;
  565.       if(ftp_inbuflen)
  566.       {
  567.         ftp_rcvState = ftp_StateDOCMD;
  568.         strcpy(ftp_outbuf,ftp_inbuf);
  569.       }
  570.       else log(inputprompt);
  571.      }
  572.      else 
  573.      {
  574.       if(!strnicmp((char *)ftp_inbuf,"abort",5L))
  575.       {
  576.         DOABORT
  577.         mget = mput = 0;
  578.         ftp_data = -1;
  579.         if(gethandle > 0) Fclose(gethandle);
  580.         if(puthandle) Fclose(puthandle);
  581.         gethandle = puthandle = 0;
  582.       }
  583.       else
  584.       {
  585.         log("\r\nTransfer in progress; only ABORT is acceptable\r\n");
  586.       }
  587.      }
  588.     }
  589.     else 
  590.     {
  591.       getline = 2;
  592.     }
  593.     ftp_inbuflen = 0;
  594.     break;
  595.  
  596.   default:
  597.     if ( key >= ' ' && ftp_inbuflen < sizeof ftp_inbuf ) 
  598.     {
  599.       ftp_inbuf[ftp_inbuflen++] = key;
  600.       ftp_inbuf[ftp_inbuflen] = 0;
  601.  
  602.       if (ftp_echoMode) log(&ftp_inbuf[ftp_inbuflen-1]);
  603.     }
  604.     if(!strnicmp(ftp_inbuf,"pass ",5)) ftp_echoMode = 0;
  605.   }
  606. }
  607.  
  608. void  dodir(int list,char *dirpath)
  609. {
  610.   long fsum = 0;
  611.   int     nfiles = 0;
  612.   struct ffblk de;  /* directory entry */
  613.   DISKINFO di;
  614.   int found;
  615.   char str[100];
  616.  
  617.   if(!dirpath || *dirpath == 0) dirpath = "*.*";
  618.   if(list == 0 && *dirpath == '-')
  619.   {
  620.     list = 1;
  621.     dirpath = strchr(dirpath,' ');
  622.     if(!dirpath) dirpath = "*.*";
  623.     else dirpath++;
  624.   } 
  625.   if((strlen(dirpath) == 2) && dirpath[1] == ':') strcat(dirpath,"\\*.*");
  626.   if(!findfirst(dirpath,&de,FA_DIREC | FA_SYSTEM | FA_HIDDEN | FA_ARCH))
  627.   {
  628.     found = 1;
  629.     if(!strrchr(dirpath,'*') && (de.ff_attrib & FA_DIREC) && de.ff_name[0] != '.')
  630.     {
  631.       strcat(dirpath,"\\*.*");
  632.       found = !findfirst(dirpath,&de,FA_DIREC | FA_SYSTEM | FA_HIDDEN | FA_ARCH);
  633.     }
  634.     while(found)
  635.     {
  636.       if(de.ff_name[0] != '.')
  637.       {
  638.         if(list != 2)
  639.         {
  640.           if(de.ff_attrib & FA_DIREC)
  641.           {
  642.             sprintf(str,"%-12s  <DIR> ",de.ff_name);
  643.           }
  644.           else
  645.           {
  646.             sprintf(str,"%-12s%7ld ",strlwr(de.ff_name),de.ff_fsize);
  647.             fsum += de.ff_fsize;
  648.           }
  649.           sprintf(str+strlen(str),"  %2.2d:%2.2d   %2.2d.%2.2d.%4.4d\r\n",
  650.           (de.ff_ftime >> 11) & 0x1f,     /* hour */
  651.           (de.ff_ftime >> 5) & 0x3f,     /* minute */
  652.           (de.ff_fdate ) & 0x1f,       /* day */
  653.           (de.ff_fdate >> 5) & 0xf,    /* month */
  654.           (de.ff_fdate >> 9) + 1980);      /* year */
  655.         }
  656.         else
  657.         {
  658.           strcpy(str,strlwr(de.ff_name));
  659.           strcat(str,"\r\n");
  660.         }
  661.         nfiles++;
  662.         if(list == 2) Fwrite(gethandle,strlen(str),str);
  663.         else w_output(p_ftp_win,str,strlen(str));
  664.       }
  665.       found = !findnext(&de);
  666.     }
  667.   }
  668.   if(list == 1)
  669.   {
  670.     Dfree(&di,0);
  671.     sprintf(str,"%5u files     %10lu bytes\r\n"
  672.         "                %10lu bytes free\r\n",
  673.     nfiles,fsum,di.b_free*di.b_secsiz*di.b_clsiz);
  674.   }
  675.   else sprintf(str,"\r\n");
  676.  
  677.   if(list == 2)
  678.   {
  679.     Fseek(0L,gethandle,0);
  680.     gethandle = 0;
  681.   }
  682.   else w_output(p_ftp_win,str,strlen(str));
  683. }
  684.  
  685. int process_cmd(void)
  686. {
  687.   int i;
  688.   char *s;
  689.   strcat(ftp_outbuf,"\r\n"); 
  690.  
  691.   ftp_outbuflen=0;
  692.  
  693.   if(!strnicmp((char *)ftp_outbuf,"port",4L))
  694.   {
  695.     isport = 1;
  696.   }
  697.   else if(!strnicmp((char *)ftp_outbuf,"get",3L))
  698.   {
  699.     memcpy((char *)&ftp_outbuf[4],(char *)&ftp_outbuf[3],strlen((char *)&ftp_outbuf[3])+1);
  700.     memcpy(ftp_outbuf,"retr",4);
  701.   }
  702.  
  703.   if(!strnicmp((char *)ftp_outbuf,"retr",4L))
  704.   {
  705.     if((px = strtok(&ftp_outbuf[5]," \r\n")) != NULL)
  706.     {
  707.       sscanf(px,"%80s",ftp_retrfile);
  708.       if((px = strtok(NULL,"\r\n")) != NULL)
  709.         sscanf(px,"%80s",ftp_retrfile);
  710.       ftp_retrfile[79] = 0;
  711.       dosify(ftp_retrfile);
  712.  
  713.       gethandle = Fcreate(ftp_retrfile,0);
  714.  
  715.       if(gethandle < 0)
  716.       {
  717.         gethandle = 0;
  718.         sprintf(logstr,"!! Could not open '%s'.\r\n",ftp_retrfile);
  719.         log(logstr);
  720.         ftp_inbuflen = 0;
  721.         log(inputprompt);
  722.         replpos = 0;
  723.         return 1;
  724.       }
  725.       else
  726.       {
  727.         getlen = 0;
  728.         tcount = 0;
  729.         btime = clock();
  730.         sprintf(logstr,"Source %s, destination %s\r\n",&ftp_outbuf[5], ftp_retrfile);
  731.         log(logstr);
  732.         strcat(ftp_outbuf,"\r\n");
  733.         if(setport() > 0) return 1;
  734.       }
  735.     }
  736.   }
  737.  
  738.   if(!strnicmp((char *)ftp_outbuf,"status",6L))
  739.   {
  740.     verb_cancel = TRUE;
  741.     getcwd(keeppath,(int)sizeof(keeppath));
  742.     sprintf(ftp_outbuf,"\r\nlocal directory is %s\r\n",keeppath);
  743.     log(ftp_outbuf);
  744.     log("Host status:\r\n");    
  745.     strcpy(ftp_outbuf,"stat\r\n");
  746.   }
  747.   else if(!strnicmp((char *)ftp_outbuf,"help",4L))
  748.   {
  749.     log("Supported commands are:\r\n");
  750.     log(" lcd ldir lls lpwd show help status abort\r\n");
  751.     log(" user passwd cd pwd dir ls get put mget mput quit\r\n");
  752.     log("Host commands:\r\n");    
  753.     verb_cancel = TRUE;
  754.   }
  755.   else if(!strnicmp((char *)ftp_outbuf,"abort",5L))
  756.   {
  757.     strcpy(ftp_outbuf,"abor\r\n");
  758.   }
  759.   else if(!strnicmp((char *)ftp_outbuf,"put",3L))
  760.   {
  761.     memcpy((char *)&ftp_outbuf[4],(char *)&ftp_outbuf[3],strlen((char *)&ftp_outbuf[3])+1);
  762.     memcpy(ftp_outbuf,"stor",4);
  763.   }
  764.   else if(strnicmp((char *)ftp_outbuf,"send",4L) == 0)
  765.   {
  766.     memcpy(ftp_outbuf,"stor",4);
  767.   }
  768.  
  769.   if(strnicmp((char *)ftp_outbuf,"stor",4L) == 0)
  770.   {
  771.     if((px = strtok(&ftp_outbuf[5]," \r\n")) != NULL)
  772.     {
  773.  
  774.       sscanf(px,"%80s\n",ftp_retrfile);
  775.       ftp_retrfile[79] = 0;
  776.       dosify(ftp_retrfile);
  777.  
  778.       puthandle = Fopen(ftp_retrfile,0);
  779.     }
  780.  
  781.     if(puthandle < 0)
  782.     {
  783.       sprintf(logstr,"Could not open '%s'.\r\n",ftp_retrfile);
  784.       log(logstr);
  785.       puthandle = 0;
  786.       ftp_inbuflen = 0;
  787.       log(inputprompt);
  788.       replpos = 0;
  789.       return 1;
  790.     }
  791.     else
  792.     {
  793.       btime = clock();
  794.       tcount = 0;
  795.       if((px = strtok(NULL," \r\n")) != NULL) strcpy(&ftp_outbuf[5],px);
  796.       sprintf(logstr,"Source %s, destination %s\r\n",ftp_retrfile,&ftp_outbuf[5]);
  797.       log(logstr);
  798.       lendata=dataindex=0;
  799.       strcat(ftp_outbuf,"\r\n");            
  800.       if(setport() > 0)   return 1;
  801.     }
  802.   }
  803.   else if(strnicmp((char *)ftp_outbuf,"dir",3L) == 0)
  804.   {
  805.     memcpy((char *)&ftp_outbuf[4],(char *)&ftp_outbuf[3],strlen((char *)&ftp_outbuf[3])+1);
  806.     memcpy(ftp_outbuf,"list",4);
  807.     gethandle = -1;
  808.     tcount = 0;
  809.     btime = clock();
  810.     if(setport() > 0)
  811.       return 1;
  812.   }
  813.   else if(strnicmp((char *)ftp_outbuf,"list",4L) == 0)
  814.   {
  815.     gethandle = -1;
  816.     tcount = 0;
  817.     btime = clock();
  818.     if(setport() > 0)
  819.       return 1;
  820.   }
  821.   else if(strnicmp((char *)ftp_outbuf,"ascii",5L) == 0)
  822.   {
  823.     strcpy(ftp_outbuf,"type a\r\n");
  824.     transfermode = 'a';
  825.   }
  826.   else if(strnicmp((char *)ftp_outbuf,"binary",6L) == 0)
  827.   {
  828.     strcpy(ftp_outbuf,"type i\r\n");
  829.     transfermode = 'i';
  830.   }
  831.   else if(strnicmp((char *)ftp_outbuf,"type",4L) == 0)
  832.   {
  833.     px = strtok(&ftp_outbuf[5]," \r\n");
  834.     if(px &&( *px == 'a' || *px == 'i'))
  835.     {
  836.       strcat(ftp_outbuf,"\r\n");
  837.       transfermode = *px;
  838.     }
  839.   }
  840.   else if(strnicmp((char *)ftp_outbuf,"pwd",3L) == 0)
  841.   {
  842.     verb_cancel = TRUE;
  843.     memcpy((char *)&ftp_outbuf[4],(char *)&ftp_outbuf[3],strlen((char *)&ftp_outbuf[3])+1);
  844.     memcpy(ftp_outbuf,"xpwd",4);
  845.   }
  846.   else if(strnicmp((char *)ftp_outbuf,"ls",2L) == 0)
  847.   {
  848.     memcpy((char *)&ftp_outbuf[4],(char *)&ftp_outbuf[2],strlen((char *)&ftp_outbuf[2])+1);
  849.     memcpy(ftp_outbuf,"nlst",4);
  850.     gethandle = -1;
  851.     tcount = 0;
  852.     btime = clock();
  853.     if(setport() >0)
  854.       return 1;
  855.   }
  856.   else if(strnicmp((char *)ftp_outbuf,"nlst",4L) == 0)
  857.   {
  858.     gethandle = -1;
  859.     tcount = 0;
  860.     btime = clock();
  861.     if(setport() >0)
  862.       return 1;
  863.   }
  864.   else if(strnicmp((char *)ftp_outbuf,"mget",4L) == 0)
  865.   {
  866.     gethandle = Fcreate(tempfile,0);
  867.  
  868.     if(gethandle < 0)
  869.     {
  870.       gethandle = 0;
  871.       sprintf(logstr,"!! Could not open intermediate file.\r\n");
  872.       log(logstr);
  873.       ftp_inbuflen = 0;
  874.       log(inputprompt);
  875.       replpos = 0;
  876.       return 1;
  877.     }
  878.     else
  879.     {
  880.       mget = gethandle;
  881.       memcpy(ftp_outbuf,"nlst",4);
  882.       if(setport() >0)
  883.         return 1;
  884.     }
  885.   }
  886.   else if(strnicmp((char *)ftp_outbuf,"mput",4L) == 0)
  887.   {
  888.     gethandle = Fcreate(tempfile,0);
  889.  
  890.     if(gethandle < 0)
  891.     {
  892.       gethandle = 0;
  893.       sprintf(logstr,"!! Could not open intermediate file.\r\n");
  894.       log(logstr);
  895.       ftp_inbuflen = 0;
  896.       log(inputprompt);
  897.       replpos = 0;
  898.       return 1;
  899.     }
  900.     else
  901.     {
  902.       mput = gethandle;
  903.       strtok(ftp_outbuf,"\r");
  904.       i = (int)strspn(&ftp_outbuf[4]," ");
  905.       s = ftp_outbuf + 4 + i;
  906.       strupr(s);
  907.       dodir(2,s);
  908.       ftp_inbuflen = 0;
  909.       replpos = 0;
  910.  
  911.       if(setport() > 0)
  912.       {
  913.         ftp_script[1] = NULL;
  914.         return 1;
  915.       }
  916.     }
  917.   }
  918.   else if(strnicmp((char *)ftp_outbuf,"cd",2L) == 0)
  919.   {
  920.     memcpy((char *)&ftp_outbuf[3],(char *)&ftp_outbuf[2],strlen((char *)&ftp_outbuf[2])+1);
  921.     memcpy((char *)ftp_outbuf,"cwd",3);
  922.   }
  923.   else if(strnicmp((char *)ftp_outbuf,"show",4L) == 0)
  924.   {
  925.     memcpy((char *)ftp_outbuf,"retr",4);
  926.     gethandle = -1;
  927.     if(setport() > 0)
  928.       return 1;
  929.   }
  930.  
  931.   /* local commands */
  932.   if((strnicmp((char *)ftp_outbuf,"lpwd",4L) == 0) || (strnicmp((char *)ftp_outbuf,"!pwd",4L) == 0))
  933.   {
  934.     getcwd(keeppath,(int)sizeof(keeppath));
  935.     sprintf(ftp_outbuf,"\r\nlocal directory is %s\r\n",keeppath);
  936.     w_output(p_ftp_win,ftp_outbuf,strlen(ftp_outbuf));
  937.     ftp_inbuflen = 0;
  938.     log(inputprompt);
  939.     replpos = 0;
  940.     return 1;
  941.   }
  942.   else if((strnicmp((char *)ftp_outbuf,"lcd",3L) == 0) || (strnicmp((char *)ftp_outbuf,"!cd",3L) == 0))
  943.   {
  944.     strtok(ftp_outbuf,"\r");
  945.     i = (int)strspn(&ftp_outbuf[3]," ");
  946.     str = &ftp_outbuf[3 + i];
  947.     strupr(str);
  948.     if(str[1] == ':' && str[0] >= 'A' && str[0] <= 'Z') Dsetdrv(str[0] - 'A');
  949.     if(Dsetpath(str))
  950.     {
  951.       sprintf(keeppath,"\r\nno such directory: %s\r\n",str);
  952.       w_output(p_ftp_win,keeppath,strlen(keeppath));
  953.     }
  954.     getcwd(keeppath,(int)sizeof(keeppath));
  955.     sprintf(ftp_outbuf,"\r\ncurrent local directory is %s\r\n",keeppath);
  956.     w_output(p_ftp_win,ftp_outbuf,strlen(ftp_outbuf));
  957.     ftp_inbuflen = 0;
  958.     log(inputprompt);
  959.     replpos = 0;
  960.     return 1;
  961.   }
  962.   else if((strnicmp((char *)ftp_outbuf,"ldir",4L) == 0) || (strnicmp((char *)ftp_outbuf,"!dir",4L) == 0))
  963.   {
  964.     strtok(ftp_outbuf,"\r");
  965.     i = (int)strspn(&ftp_outbuf[4]," ");
  966.     s = ftp_outbuf + 4 + i;
  967.     strupr(s);
  968.     dodir(1,s);
  969.     ftp_inbuflen = 0;
  970.     log(inputprompt);
  971.     replpos = 0;
  972.     return 1;
  973.   }
  974.   else if((strnicmp((char *)ftp_outbuf,"lls",3L) == 0) || (strnicmp((char *)ftp_outbuf,"!ls",3L) == 0))
  975.   {
  976.     strtok(ftp_outbuf,"\r");
  977.     i = (int)strspn(&ftp_outbuf[3]," ");
  978.     s = ftp_outbuf + 3 + i;
  979.     strupr(s);
  980.     dodir(0,s);
  981.     ftp_inbuflen = 0;
  982.     log(inputprompt);
  983.     replpos = 0;
  984.     return 1;
  985.   }
  986.   else if(strnicmp((char *)ftp_outbuf,"prompt",6L) == 0)
  987.   {
  988.     interactive = !interactive;
  989.     log(interactive ? "interactive mode on\r\n" : "interactive mode off\r\n"); 
  990.     ftp_inbuflen = 0;
  991.     log(inputprompt);
  992.     replpos = 0;
  993.     return 1;
  994.   }
  995.   else if(strnicmp((char *)ftp_outbuf,"verbose",7L) == 0)
  996.   {
  997.     verbose = !verbose;
  998.     ftp_inbuflen = 0;
  999.     log(inputprompt);
  1000.     replpos = 0;
  1001.     return 1;
  1002.   }
  1003.   else
  1004.   {
  1005.     ftp_inbuflen = 0;
  1006.     ftp_outbuflen = (int)strlen((char *)ftp_outbuf);
  1007.     ftp_outbufix = 0;
  1008.     ftp_rcvState = ftp_StateSENDCOMMAND;
  1009.     /* fall through */
  1010.   }
  1011.   return 0;
  1012. }
  1013.  
  1014. int setport(void)
  1015. {
  1016. #define TRIES 10
  1017.  
  1018.   int state,i;
  1019.   char *term;
  1020.   long tcp_buff;
  1021.   
  1022.   desti.Port = FTP_DATA;
  1023.   term = (char *)getenv("FTPWIN");
  1024.   if(term) tcp_buff = atol(term);
  1025.   else tcp_buff = FTPWND;
  1026.   if(gethandle < 0) tcp_buff = DIRWND;
  1027.   
  1028.   for(i = 0;i < TRIES;i++)
  1029.   {
  1030.    ftp_data = (int)  tcp_open(0,&desti,PASSIV,60,tcp_buff);
  1031.    while(ftp_data > 0 && (state = (int)tcp_stat(ftp_data,&tstat)) != LISTEN)
  1032.    {
  1033.     evnt_timer(10,0);
  1034.     if(state == CLOSED)
  1035.     {
  1036.       ftp_data = -1;
  1037.       break;
  1038.     }
  1039.    }
  1040.    if(ftp_data >0) break;
  1041.    w_info(p_ftp_win,"<Status: retrying to open data connection>");
  1042.    evnt_timer(10,0);
  1043.   }
  1044.   
  1045.   if(ftp_data <= 0)
  1046.   {
  1047.     ftp_script[0] = NULL;
  1048.     ftp_rcvState = ftp_StateGETCMD;
  1049.     w_info(p_ftp_win,"<Error: Could not open data connection>");
  1050.     log(inputprompt);
  1051.     replpos = 0;
  1052.   }
  1053.   else
  1054.   {
  1055.     my.Port = tstat.TCP_Port;
  1056.     sprintf(ftpscriptbuf[0],"port %d,%d,%d,%d,%d,%d\r\n",my.IPAddr[0],my.IPAddr[1],my.IPAddr[2],my.IPAddr[3],my.Port/256,my.Port&255);
  1057.     ftp_script[0] = ftpscriptbuf[0];
  1058.     ftp_script[1] = NULL;
  1059.     isport = 1;
  1060.     strcpy(ftpscriptbuf[1],ftp_outbuf);
  1061.     ftp_script[1] = ftpscriptbuf[1];
  1062.     ftp_script[2] = NULL;
  1063.     ftp_scriptline = 0;
  1064.   }
  1065.   return(ftp_data);
  1066. }
  1067.  
  1068. int do_mget()
  1069. {
  1070.   int i;
  1071.  
  1072.  if(!getline)
  1073.  {
  1074.   strcpy(ftp_outbuf,"retr ");
  1075.  
  1076.   i = 5;
  1077.   while(Fread(mget,1,&ftp_outbuf[i]) == 1 && ftp_outbuf[i] != '\n') i++;
  1078.  
  1079.   if(ftp_outbuf[i] != '\n')
  1080.   {
  1081.     Fclose(mput);
  1082.     Fdelete(tempfile);
  1083.     mget = 0;
  1084.     log(inputprompt);
  1085.     return 0;
  1086.   }
  1087.   ftp_outbuf[i+1] = 0;
  1088.  
  1089.   if(ftp_outbuf[i-1] != '\r')
  1090.   {
  1091.     strcpy(&ftp_outbuf[i],"\r\n");
  1092.     i++;
  1093.   }
  1094.   if(interactive)
  1095.   {
  1096.     log("\r\n");
  1097.     strcpy(logstr,ftp_outbuf);
  1098.     memcpy(logstr," get ",5L);
  1099.     strcpy(&logstr[i-1]," ? ");
  1100.     log(logstr);
  1101.     getline = 1;
  1102.     return 0;
  1103.   }
  1104.  }
  1105.  else if(getline == 2)
  1106.  {
  1107.    getline = 0;
  1108.    if(!strnicmp(ftp_inbuf,"y",1)) return 1;    /* do file */
  1109.    else return 0;                /* skip file */
  1110.  }
  1111.  else return 0;
  1112.  return 1;
  1113. }
  1114.  
  1115. int do_mput()
  1116. {
  1117.   int i;
  1118.  
  1119.  if(!getline)
  1120.  {
  1121.   strcpy(ftp_outbuf,"stor ");
  1122.   i = 5;
  1123.   while(Fread(mput,1,&ftp_outbuf[i]) == 1 && ftp_outbuf[i] != '\n') i++;
  1124.   if(ftp_outbuf[i] != '\n')
  1125.   {
  1126.     Fclose(mput);
  1127.     Fdelete(tempfile);
  1128.     mput = 0;
  1129.     log(inputprompt);
  1130.     return 0;
  1131.   }
  1132.   ftp_outbuf[i+1] = 0;
  1133.   if(interactive)
  1134.   {
  1135.     log("\r\n");
  1136.     strcpy(logstr,ftp_outbuf);
  1137.     memcpy(logstr," put ",5L);
  1138.     strcpy(&logstr[i-1]," ? ");
  1139.     log(logstr);
  1140.     getline = 1;
  1141.     return 0;
  1142.   }
  1143.  }
  1144.  else if(getline == 2)
  1145.  {
  1146.    getline = 0;
  1147.    if(!strnicmp(ftp_inbuf,"y",1)) return 1;    /* do file */
  1148.    else return 0;                /* skip file */
  1149.  }
  1150.  else return 0;
  1151.  return 1;
  1152. }
  1153.  
  1154. void dosify(char * s)
  1155. {
  1156.   while(*s)
  1157.   {
  1158.     if(*s == '/')    *s = '\\';
  1159.     s++;
  1160.   }
  1161. }
  1162.